import React from 'react';
import { Input, Field, Button, Message, Form, Dialog, Balloon, Select } from '@teamix/ui';
import { navigate } from 'utils/router';
import FilePanel from 'components/filePanel';
import Editor from 'components/editor';
import FileBasicForm from 'components/fileBasicForm';
import UILessAssociateTask from 'components/UILessAssociateTask';
import exceed from 'utils/apimap';
import utils from 'utils/index';
import { getFeature } from 'utils/features';
import { getAllFiles } from 'api';
import ListLoading from 'atComponents/ListLoading';
import intl from '../../../../../../../../locale';

const { Tooltip } = Balloon;
const { pathResource, resourceSubject } = window.FORCE;
export default class NewFiles extends React.Component {
  constructor(props) {
    super(props);
    // file_path 初始值在这里设，而不是init里，否则会导致 react-monaco-editor language 报错
    this.field = new Field(this, {
      values: {
        file_path: utils.getUrlSearchParam('file_name') || '',
      },
    });

    this.state = {
      visible: false,
      submitting: false,
      existFileList: [],
      task_ids: '',
      // 正在请求readme模板
      isLoadingTemplate: false,
      templates: [],
      // 默认模板为空
      templateType: '',
      // 新建支持的所有模板
      allTemplateObj: {},
      ignore_type: '',
      ignore_lang: '',
    };
  }

  componentDidMount() {
    window.onbeforeunload = function () {
      return intl.get({
        id: 'code-assets.containers.newFiles.AreYouSureYouWant',
        defaultMessage: '确定离开此页面？',
      });
    };
    if (window.FORCE.pathResource.isEmpty !== 'true') {
      getAllFiles()
        .then((result) => {
          result.shift();
          this.setState({
            existFileList: result,
          });
        })
        .catch((err) => {
          console.log(err);
        });
      this.getReadMeTemplate();
      this.getIgnoreTemplate();
    } else {
      // 空库新建readme 增加模板
      const isReadme = utils.getUrlSearchParam('file_name') === 'README.md';
      if (isReadme) {
        this.getReadMeTemplate(true);
      } else {
        this.getReadMeTemplate();
        this.getIgnoreTemplate();
      }
    }
  }

  getReadMeTemplate = (isReadme) => {
    this.setState({
      isLoadingTemplate: true,
    });

    exceed
      .fetch({
        api: 'project.file.readme.template',
        data: {
          readme_types: 'empty,user_guide',
        },
      })
      .then((result) => {
        const templates = result.slice(1);
        if (isReadme) {
          this.setState({
            allTemplates: templates,
            templates,
            isLoadingTemplate: false,
          });

          const { templateType } = this.state;
          const curTemplate = templates.find(
            (item) => item.type && item.type.toLowerCase() === templateType,
          );
          this.field.setValue('content', curTemplate.content || '');
        } else {
          this.setState({
            allTemplates: templates,
            isLoadingTemplate: false,
          });
        }
      })
      .fail(() => {
        this.setState({
          isLoadingTemplate: false,
        });
      });
  };

  getIgnoreTemplate = () => {
    if (!getFeature('project.files.newFiles.needGetIgnoreTemplate')) {
      return;
    }

    this.setState({
      isLoadingTemplate: true,
    });

    exceed
      .fetch({
        api: 'project.file.ignore.lang',
      })
      .then((result) => {
        this.setState({
          allTemplateObj: result || {},
          isLoadingTemplate: false,
        });
      })
      .fail(() => {
        this.setState({
          isLoadingTemplate: false,
        });
      });
  };

  // 新建文件
  // 接口见：http://gitlab.alibaba-inc.com/help/api/repository_files.md
  createFile = (formData, commit_message) => {
    const { file_path, content = '', branch_name, task_ids } = formData;
    const revision = resourceSubject.revision || 'master';
    return exceed
      .fetch({
        api: 'projects.files.new.associateTask',
        data: {
          project_id: pathResource.id,
          task_ids,
          file_path,
          branch_name,
          commit_message,
          content,
        },
      })
      .then(() => {
        Message.success({
          title: intl.get({
            id: 'code-assets.containers.newFiles.SubmittedSuccessfully',
            defaultMessage: '提交成功',
          }),
        });

        this.props.updateData({
          hasPush: true,
        });

        window.onbeforeunload = null; // 清空阻止跳转事件

        navigate(
          `/${pathResource.fullPath}/blob/${utils.revisionEncodeURI(
            revision,
          )}/${utils.filepathEncodeURI(formData.file_path)}`,
          { state: { forceUpdate: true } },
        );

        this.setState({ submitting: false });
      })
      .fail(() => {
        this.setState({ submitting: false });
      });
  };

  onFormSave = () => {
    if (this.state.submitting) return;
    this.setState({ submitting: true });
    const { resourcePath } = this.props;
    const isMaster = utils.getUrlSearchParam('isMaster');
    this.field.validate((errors) => {
      if (!errors) {
        const formData = this.field.getValues();
        const commit_message = formData.commit_message_content
          ? `${formData.commit_message_title}\n${formData.commit_message_content}`
          : formData.commit_message_title;
        // 给文件名拼接上当前路径
        if (!isMaster) {
          formData.file_path = `${resourcePath}${resourcePath && '/'}${formData.file_path}`;
        }

        // file_path,去掉/两侧的空格
        const regExp = new RegExp(' */ *', 'g');
        formData.file_path = formData.file_path.replace(regExp, '/');

        if (this.state.task_ids) {
          formData.task_ids = this.state.task_ids;
        }

        this.createFile(formData, commit_message);
      } else if (errors.file_path) {
        // 如果是路径未填，提示输入路径
        Message.error({
          title: intl.get({
            id: 'code-assets.containers.newFiles.EnterAFileName',
            defaultMessage: '请输入文件名',
          }),
        });

        this.setState({ submitting: false });
      }
    });
  };

  nameValidator = (rule, value, callback) => {
    if (!value) {
      callback();
      return;
    }
    if (/^(?!(\/)).+$/.test(value) === false) {
      callback(
        intl.get({
          id: 'code-assets.containers.newFiles.ANewFileCannotStart',
          defaultMessage: '新建文件不能直接以 / 开头',
        }),
      );
      return;
    }
    if (!new RegExp('^[\\u4e00-\\u9fa5a-z A-Z0-9_\\-\\.\\/]*$').test(value)) {
      callback(
        intl.get({
          id: 'code-assets.containers.newFiles.TheNameCanOnlyContain',
          defaultMessage: '名称只能包含中英文、数字、"_"、"-"、"."以及空格',
        }),
      );
      return;
    }

    const { resourcePath } = this.props;
    const newFilePath = `${resourcePath}${resourcePath && '/'}${value}`;

    const { existFileList } = this.state;
    existFileList.forEach((item) => {
      if (newFilePath === item.path) {
        callback(
          intl.get({
            id: 'code-assets.containers.newFiles.TheFileAlreadyExists',
            defaultMessage: '文件已存在',
          }),
        );
      }
    });

    callback();
  };

  cancleConfirm = () => {
    window.onbeforeunload = null; // 清空阻止跳转事件
    this.confirmResult = window.confirm(
      intl.get({
        id: 'code-assets.containers.newFiles.YouAreCreatingANew',
        defaultMessage: '您正在新建文件，是否确认离开？',
      }),
    );
    if (!this.confirmResult) {
      return false;
    } else {
      window.onbeforeunload = null; // 清空阻止跳转事件
      const { revision } = window.FORCE.resourceSubject;
      if (revision) {
        navigate(`/${pathResource.fullPath}/tree/${revision}`, { state: { forceUpdate: true } });
      } else {
        navigate(`/${pathResource.fullPath}`, { state: { forceUpdate: true } });
      }
    }
  };

  onOpen = () => {
    if (this.field.values.file_path.match(/^[ ]*$/)) {
      this.field.values.file_path = '';
    }
    this.field.validate((errors) => {
      if (!errors) {
        this.setState({
          visible: true,
        });
      }
    });
  };

  onClose = () => {
    this.setState({
      visible: false,
    });
  };

  renderTemplateSelect = () => {
    const { templates, templateType } = this.state;
    if (templates.length) {
      return (
        <div className="new-file-template-select">
          <Select
            value={templateType}
            onChange={(value) => {
              this.setState({ templateType: value });
              const curTemplate =
                templates.find((item) => item.type && item.type.toLowerCase() === value) || {};
              this.field.setValue('content', curTemplate.content || '');
            }}
          >
            <Select.Option value="">
              {intl.get({
                id: 'code-assets.containers.newFiles.DoNotSelectATemplate',
                defaultMessage: '不选择模板',
              })}
            </Select.Option>
            <Select.Option value="empty">
              {intl.get({
                id: 'code-assets.containers.newFiles.ReadmeTemplate',
                defaultMessage: 'readme模板',
              })}
            </Select.Option>
          </Select>
        </div>
      );
    }
    return null;
  };

  selectLang = (lang) => {
    this.setState({
      ignore_lang: lang || '',
    });

    this.getLangContent(lang);
  };

  getLangContent = (lang) => {
    if (!lang) {
      this.field.setValue('content', '');
      return;
    }
    exceed
      .fetch({
        api: 'project.file.ignore.template',
        data: {
          git_ignore_type: lang,
        },
      })
      .then((result) => {
        this.field.setValue('content', result.content || '');
      });
  };

  renderIgnoreTypes = () => {
    const { templateType, ignore_type, allTemplateObj, ignore_lang, allTemplates } = this.state;
    const isReadme = utils.getUrlSearchParam('file_name') === 'README.md';
    if (allTemplateObj && Object.keys(allTemplateObj).length) {
      const filterLanges = ignore_type ? allTemplateObj[ignore_type] : [];
      return (
        <div className="new-file-template-select">
          <Select
            value={templateType}
            onChange={(value) => {
              if (value === 'empty') {
                this.setState({
                  templateType: value,
                  ignore_type: '',
                });

                const curTemplate =
                  allTemplates.find((item) => item.type && item.type.toLowerCase() === value) || {};
                this.field.setValue('content', curTemplate.content || '');
                this.field.setValue(
                  'file_path',
                  (this.field.getValue('file_path') || '').replace('.gitignore', ''),
                );
                return;
              }
              this.setState({
                ignore_type: value || '',
                templateType: value || '',
              });

              if (!value) {
                this.setState({
                  ignore_lang: '',
                });

                this.field.setValue('content', '');
                this.field.setValue(
                  'file_path',
                  (this.field.getValue('file_path') || '').replace('.gitignore', ''),
                );
              } else {
                this.field.setValue('content', '');
                this.field.setValue(
                  'file_path',
                  `${this.field.getValue('file_path') || ''}.gitignore`,
                );
              }
            }}
            style={{ marginRight: 20 }}
          >
            <Select.Option value="">
              {intl.get({
                id: 'code-assets.containers.newFiles.DoNotSelectATemplate.1',
                defaultMessage: '不选择模板类型',
              })}
            </Select.Option>
            {isReadme ? (
              <Select.Option value="empty">
                {intl.get({
                  id: 'code-assets.containers.newFiles.ReadmeTemplate',
                  defaultMessage: 'readme模板',
                })}
              </Select.Option>
            ) : (
              <Select.Option value="git_ignore_types">.gitignore</Select.Option>
            )}
          </Select>

          {templateType !== 'empty' ? (
            <Select
              value={ignore_lang}
              onChange={this.selectLang}
              showSearch
              disabled={!filterLanges.length}
            >
              <Select.Option value="">
                {intl.get({
                  id: 'code-assets.containers.newFiles.DoNotSelectATemplate',
                  defaultMessage: '不选择模板',
                })}
              </Select.Option>
              {filterLanges.map((lang) => {
                return <Select.Option value={lang}>{lang}</Select.Option>;
              })}
            </Select>
          ) : null}
        </div>
      );
    }
  };

  render() {
    const { resourcePath } = this.props;
    const revision = resourceSubject.revision || 'master';
    const { init } = this.field;
    const fileName = this.field.getValue('file_path');
    const isMaster = utils.getUrlSearchParam('isMaster');
    const fileRootPath = resourcePath && resourcePath.split('/').join(' / ');
    const { isLoadingTemplate } = this.state;
    return (
      <div className="project-new-files">
        <FilePanel>
          <FilePanel.Header>
            {isMaster && isMaster === '1' ? null : (
              <span style={{ marginRight: resourcePath ? 16 : 0 }}>
                {resourcePath && `${fileRootPath} /`}
              </span>
            )}

            <Form field={this.field} className="project-new-files-form">
              <Form.Item
                help={
                  this.field.getState('file_path') === 'error'
                    ? this.field.getError('file_path')
                    : intl.get({
                        id: 'code-assets.containers.newFiles.EnterToCreateAFile',
                        defaultMessage: '输入「/」可将文件创建到新文件夹下',
                      })
                }
                className="project-new-files-input"
              >
                <Input
                  {...init('file_path', {
                    rules: [
                      {
                        required: true,
                        message: intl.get({
                          id: 'code-assets.src.utils.locale.TheFileNameIsRequired',
                          defaultMessage: '文件名为必填项',
                        }),
                      },

                      { validator: this.nameValidator },
                    ],
                  })}
                  placeholder={intl.get({
                    id: 'code-assets.containers.newFiles.EnterAFileNameOr',
                    defaultMessage: '请输入文件名或文件路径',
                  })}
                  autoFocus
                  style={{ width: '300px' }}
                />
              </Form.Item>
            </Form>
          </FilePanel.Header>
          {isLoadingTemplate ? (
            <ListLoading />
          ) : (
            <FilePanel.Body noPadding>
              {this.renderTemplateSelect()}
              {this.renderIgnoreTypes()}
              <Editor
                {...init('content')}
                fileName={fileName}
                editorStyle={{ height: 'calc(100vh - 76px - 162px - 60px)' }}
              />
              <div style={{ margin: '20px 0' }}>
                <Button
                  disabled={
                    this.field.getValue('file_path') === null ||
                    this.field.getState('file_path') === 'error'
                  }
                  type="primary"
                  onClick={this.onOpen}
                >
                  {intl.get({ id: 'code-assets.containers.newFiles.Save', defaultMessage: '保存' })}
                </Button>
                <Button onClick={this.cancleConfirm} style={{ marginLeft: 16 }} type="normal">
                  {intl.get({
                    id: 'code-assets.containers.newFiles.Cancel',
                    defaultMessage: '取消',
                  })}
                </Button>
                <Dialog
                  title={
                    <Tooltip
                      trigger={
                        <div className="file-form-title">
                          {intl.get(
                            {
                              id: 'code-assets.containers.newFiles.SubmitToRevision',
                              defaultMessage: '提交到 {revision}',
                            },
                            { revision },
                          )}
                        </div>
                      }
                      align="t"
                    >
                      <span style={{ wordBreak: 'break-all' }}>
                        {intl.get({
                          id: 'code-assets.containers.newFiles.Submit',
                          defaultMessage: '提交到',
                        })}
                        {revision}
                      </span>
                    </Tooltip>
                  }
                  visible={this.state.visible}
                  onOk={this.onFormSave}
                  onCancel={this.onClose}
                  onClose={this.onClose}
                  style={{ width: '600px' }}
                  okProps={{
                    children: intl.get({
                      id: 'code-assets.containers.newFiles.Submitted',
                      defaultMessage: '提交',
                    }),
                    loading: this.state.submitting,
                  }}
                  cancelProps={{
                    children: intl.get({
                      id: 'code-assets.containers.newFiles.Cancel',
                      defaultMessage: '取消',
                    }),
                  }}
                >
                  <FileBasicForm
                    field={this.field}
                    defaultCommitMsg={intl.get(
                      {
                        id: 'code-assets.containers.newFiles.CreateFilename',
                        defaultMessage: '新建 {fileName}',
                      },
                      { fileName },
                    )}
                  />
                  <UILessAssociateTask
                    useBy="submit"
                    onChange={(items) => {
                      if (!items.map) {
                        return;
                      }
                      const task_ids = items.map((item) => {
                        return item._id;
                      });
                      this.setState({
                        task_ids: task_ids.join(','),
                      });
                    }}
                  />
                </Dialog>
              </div>
            </FilePanel.Body>
          )}
        </FilePanel>
      </div>
    );
  }
}
